#include "ASScreen.h"
#include "ASScreenMgr.h"
#include "..\control\ASLabel.h"
#include "..\control\ASWaiting.h"
#include "..\control\ASScrollText.h"
#include "..\control\ASButton.h"
#include "..\control\ASAdvbar.h"
#include "ASTestScreen.h"
#include "ASLoadingScreen.h"
#include "ASOptionScreen.h"
#include "ASPopupScreen.h"
#include "ASConfirmScreen.h"
#include "ASWaitingScreen.h"
#include "ASNumberScreen.h"
#include "ASDateTimeScreen.h"
#include "ASCustomScreen.h"
#include "ASFTDataScreen.h"
#include "ASFTTypeScreen.h"
#include "ASFTDetailScreen.h"
#include "ASFTStatScreen.h"
#include "ASFTSettingScreen.h"
#include "ASFTAboutScreen.h"

/************************************************************************/
/* function declaration                                                 */
/************************************************************************/
extern void as_screen_repaint(as_screen* screen_p);


/*
 *	[description] check the screen if small by given screen type
    [return] TRUE : given type belongs small screen
             FALSE : not small screen
 */
ASINT as_screen_is_small_screen(as_screen_type type)
{
    ASINT is_small = FALSE;

    if(type == AS_SCREEN_OPTION
       || type == AS_SCREEN_CONFIRM
       || type == AS_SCREEN_POPUP
       || type == AS_SCREEN_WAITING
       || type == AS_SCREEN_NUMBER
       || type == AS_SCREEN_DATETIME
       || type == AS_SCREEN_FTTYPE)
    {
        is_small = TRUE;
    }
    else
    {
        is_small = FALSE;
    }

    return is_small;
}

static void as_screen_paint(as_screen* screen_p)
{
    ASINT i = 0;
    ASUINT8* buf = NULL;

    if(!screen_p )
    {
        return;
    }

    //draw bg firstly
    if(!screen_p->is_small_screen)
    {
        buf = as_get_layer_buffer_by_hdlr(0);

        if(screen_p->bg_img)
        {
            ((as_control*)screen_p->bg_img)->paint_hdlr((as_control*)screen_p->bg_img);
        }
        else
        {
            as_rect a;
            a.x = a.y = 0;
            a.w = as_get_lcd_width();
            a.h = as_get_lcd_height();
            as_fill_rect(&a, screen_p->bg_color, screen_p->bg_color);
        }
    }
    else
    {
#ifdef AS_RUN_ON_SKY
        mrc_EffSetCon(0, 0, as_get_lcd_width(), as_get_lcd_height(), 180, 180, 180);
#endif
    }

#if defined(AS_RUN_ON_SKY)
    as_reset_clip();
#endif

    //paint from stack bottom
    for (i = 0; i <= screen_p->ctrl_stack_top; i++)
    {
        screen_p->ctrl_stack[i]->paint_hdlr(screen_p->ctrl_stack[i]);
#if defined(AS_RUN_ON_SKY)
        as_reset_clip();
#endif
    }
}

static void as_screen_penevt_hdlr(as_screen* screen_p, ASINT event, ASINT x, ASINT y)
{
    ASINT i = 0;

    if(!screen_p)
    {
        return;
    }

    for(i = screen_p->ctrl_stack_top; i >= 0; i--)
    {
        if(screen_p->ctrl_stack[i] && screen_p->ctrl_stack[i]->pen_hdlr)
        {
            as_ret pen_ret = screen_p->ctrl_stack[i]->pen_hdlr(screen_p->ctrl_stack[i], event, x, y);

            if(pen_ret == AS_OK)
                return;
            else if(pen_ret == AS_IGNORE)
                continue;
            else
                return;
        }
    }
}

static void as_screen_keyevt_hdlr(as_screen* screen_p, ASINT event, ASINT keycode)
{
    ASINT i = 0;

    if(!screen_p)
    {
        return;
    }

    for(i = screen_p->ctrl_stack_top; i >= 0; i--)
    {
        if(screen_p->ctrl_stack[i] && screen_p->ctrl_stack[i]->key_hdlr)
        {
            as_ret key_ret = screen_p->ctrl_stack[i]->key_hdlr(screen_p->ctrl_stack[i], event, keycode);

            if(key_ret == AS_OK)
                return;
            else if(key_ret == AS_IGNORE)
                continue;
            else
                return;
        }
    }
}

static void as_screen_flush(as_screen* screen_p)
{
    AS_UNUSED(screen_p);
#if defined(AS_RUN_ON_SKY)
    as_reset_clip();
    as_advbar_flush();
#endif
    as_flush();
}


static as_control* as_screen_add_ctrl(as_screen* screen_p,
                                      as_control_type type, as_rect area,
                                      ASINT exta_param_cnts, void* exta_param_p[])
{
    as_control* ctrl_p = NULL;

    if(!screen_p)
        return ctrl_p;

    if(screen_p->ctrl_stack_top >= AS_SCREEN_MAX_CTRL_COUNTS - 1)
    {
        return ctrl_p;
    }

    ctrl_p = as_ctrl_create(type, area, exta_param_cnts, exta_param_p);

    if(ctrl_p)
    {
        screen_p->ctrl_stack_top++;
        screen_p->ctrl_stack[screen_p->ctrl_stack_top] = ctrl_p;
    }

    return ctrl_p;
}

static as_ret as_screen_pop_and_delete_ctrl(as_screen* screen_p)
{
    as_ret ret = AS_OK;

    if(!screen_p)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    if(screen_p->ctrl_stack_top == -1)
    {
        return ret;
    }

    as_ctrl_destroy(screen_p->ctrl_stack[screen_p->ctrl_stack_top]);
    screen_p->ctrl_stack[screen_p->ctrl_stack_top] = NULL;
    screen_p->ctrl_stack_top--;
    return ret;
}

static as_ret as_screen_delete_ctrl(as_screen* screen_p, as_control* ctrl_p)
{
    as_ret ret = AS_OK;

    if(!screen_p)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    if(ctrl_p == NULL)
    {
        //just pop one from ctrl stack
        return as_screen_pop_and_delete_ctrl(screen_p);
    }
    else
    {
        ASINT i = 0;

        for (; i <= screen_p->ctrl_stack_top; i++)
        {
            if(screen_p->ctrl_stack[i] == ctrl_p)
            {
                break;
            }
        }

        if(i > screen_p->ctrl_stack_top)
        {
            ret = AS_INTERNAL_ERROR;
            return ret;
        }

        as_ctrl_destroy(screen_p->ctrl_stack[i]);
        screen_p->ctrl_stack[i] = NULL;

        for (; i < screen_p->ctrl_stack_top; i++)
        {
            screen_p->ctrl_stack[i] = screen_p->ctrl_stack[i + 1];
        }

        screen_p->ctrl_stack[screen_p->ctrl_stack_top] = NULL;
        screen_p->ctrl_stack_top--;
        return ret;
    }
}

static as_ret as_screen_delete_ctrl_by_type(as_screen* screen_p, as_control_type type)
{
    as_ret ret = AS_OK;
    //TODO
    AS_UNUSED(screen_p);
    AS_UNUSED(type);
    return ret;
}

static as_ret as_screen_clear_ctrl_stack(as_screen* screen_p)
{
    as_ret ret = AS_OK;
    ASINT i = 0;

    if(!screen_p)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    for(i = screen_p->ctrl_stack_top; i >= 0; i--)
    {
        as_ctrl_destroy(screen_p->ctrl_stack[i]);
        screen_p->ctrl_stack[i] = NULL;
    }

    screen_p->ctrl_stack_top = -1;
    return ret;
}

static ASINT as_screen_get_ctrl_counts(as_screen* screen_p)
{
    if(!screen_p)
    {
        return -1;
    }
    else
    {
        return screen_p->ctrl_stack_top + 1;
    }
}

static as_ret as_screen_set_bg_color(as_screen* screen_p, ASINT color)
{
    as_ret ret = AS_OK;

    if(!screen_p)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    screen_p->bg_color = color;
    return ret;
}

static as_ret as_screen_set_bg_image(as_screen* screen_p, ASWSTR path, as_image_src_type type)
{
    as_ret ret = AS_OK;
    ASUINT8* layer_buf = NULL;
    as_rect area;
    ASUINT param[3];

    if(!screen_p || !path || as_wstrlen(path) <= 0)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    if(screen_p->bg_img)
    {
        as_ctrl_destroy((as_control*)screen_p->bg_img);
    }

    layer_buf = as_get_layer_buffer_by_hdlr(0);
    area.x = area.y = 0;
    area.w = as_get_lcd_width();
    area.h = as_get_lcd_height();
    param[0] = (ASUINT)type;
    param[1] = (ASUINT)path;
    param[2] = (ASUINT)FALSE;
    screen_p->bg_img = (as_image*)as_ctrl_create(AS_CTRL_IMAGE, area, 3, (void**)param);

    if(screen_p->bg_img == NULL)
    {
        ret = AS_INTERNAL_ERROR;
        return ret;
    }

    if(screen_p->bg_img->img_w < area.w
       || screen_p->bg_img->img_h < area.h)
    {
        screen_p->bg_img->set_show_type((as_control*)screen_p->bg_img, AS_IMAGE_TILED);
    }

    return ret;
}

static void as_screen_goback(ASINT if_redraw)
{
    as_screen* scr_p;
    as_screen_manager* scr_mgr_p = as_get_screen_stack_instance();
    scr_mgr_p->delete_and_pop_screen();
    //if(if_redraw)
    //{
    //    scr_p = scr_mgr_p->get_cur_screen();
    //    if(scr_p)
    //    {
    //        scr_p->clear();
    //        scr_p->repaint_hdlr(scr_p);
    //        scr_p->flush_hdlr(scr_p);
    //    }
    //}
}

as_screen* as_screen_calloc(as_screen_type type)
{
    //as_log_str("as_screen_calloc");
    as_log_ui("<ui>----~~~~~~~as_screen_calloc~~~~~~~type[%d]", type);

    switch (type)
    {
#ifdef AS_TEST_SCREEN_ENABLE

        case AS_SCREEN_TEST:
            return (as_screen*)as_calloc(sizeof(as_test_screen));
#endif

        case AS_SCREEN_LOADING:
            return (as_screen*)as_calloc(sizeof(as_loading_screen));

        case AS_SCREEN_OPTION:
            return (as_screen*)as_calloc(sizeof(as_option_screen));

        case AS_SCREEN_POPUP:
            return (as_screen*)as_calloc(sizeof(as_popup_screen));

        case AS_SCREEN_CONFIRM:
            return (as_screen*)as_calloc(sizeof(as_confirm_screen));

        case AS_SCREEN_WAITING:
            return (as_screen*)as_calloc(sizeof(as_waiting_screen));

        case AS_SCREEN_NUMBER:
            return (as_screen*)as_calloc(sizeof(as_number_screen));

        case AS_SCREEN_DATETIME:
            return (as_screen*)as_calloc(sizeof(as_datetime_screen));

        case AS_SCREEN_CUSTOM:
            return (as_screen*)as_calloc(sizeof(as_custom_screen));

        case AS_SCREEN_FTDATA:
            return (as_screen*)as_calloc(sizeof(as_ftdata_screen));

        case AS_SCREEN_FTTYPE:
            return (as_screen*)as_calloc(sizeof(as_fttype_screen));

        case AS_SCREEN_FTDETAIL:
            return (as_screen*)as_calloc(sizeof(as_ftdetail_screen));

        case AS_SCREEN_FTSTAT:
            return (as_screen*)as_calloc(sizeof(as_ftstat_screen));

        case AS_SCREEN_FTSTAT_SUB:
            return (as_screen*)as_calloc(sizeof(as_ftstatsub_screen));

        case AS_SCREEN_FTSETTING:
            return (as_screen*)as_calloc(sizeof(as_ft_setting_screen));

        case AS_SCREEN_FTABOUT:
            return (as_screen*)as_calloc(sizeof(as_ft_about_screen));

        case AS_SCREEN_FTABOUT_SUB:
            return (as_screen*)as_calloc(sizeof(as_ft_aboutsub_screen));

        default:
            //warn
            return NULL;
    }
}

/*
 *	1,call function
 */
as_ret as_screen_pause(as_screen* screen_p)
{
    ASINT i;

    if(!screen_p)
        return AS_INVALID_PARAM;

    for(i = 0; i <= screen_p->ctrl_stack_top; i++)
    {
        if(screen_p->ctrl_stack[i])
        {
            screen_p->ctrl_stack[i]->set_hidden(screen_p->ctrl_stack[i], ASTRUE);
        }
    }

    switch(screen_p->screen_type)
    {
            //case AS_SCREEN_CONTENT:
            //    as_content_screen_pause(screen_p);
            //    break;
            //default:
            //    break;
    }

    return AS_OK;
}

as_ret as_screen_resume(as_screen* screen_p)
{
    ASINT i;

    if(!screen_p)
        return AS_INVALID_PARAM;

    for(i = 0; i <= screen_p->ctrl_stack_top; i++)
    {
        if(screen_p->ctrl_stack[i])
        {
            screen_p->ctrl_stack[i]->set_hidden(screen_p->ctrl_stack[i], ASFALSE);
        }
    }

    switch(screen_p->screen_type)
    {
            //case AS_SCREEN_CONTENT:
            //    as_content_screen_resume(screen_p);
            //    break;
            //default:
            //    break;
    }

    screen_p->repaint_hdlr(screen_p);
    screen_p->flush_hdlr(screen_p);
    return AS_OK;
}

as_ret as_screen_init(as_screen* screen_p, as_screen_type screen_type)
{
    if(screen_p == NULL)
    {
        return AS_INVALID_PARAM;
    }

    memset(screen_p, 0, sizeof(as_screen));
    screen_p->init_hdlr = as_screen_init;
    screen_p->deinit_hdlr = as_screen_deinit;
    screen_p->pause = as_screen_pause;
    screen_p->resume = as_screen_resume;
    screen_p->is_inited = TRUE;
    screen_p->screen_type = screen_type;
    screen_p->is_small_screen = as_screen_is_small_screen(screen_p->screen_type);
    screen_p->paint_hdlr = as_screen_paint;
    screen_p->repaint_hdlr = as_screen_repaint;
    screen_p->flush_hdlr = as_screen_flush;
    screen_p->ctrl_stack_top = -1;
    screen_p->add_ctrl = as_screen_add_ctrl;
    screen_p->delete_ctrl = as_screen_delete_ctrl;
    screen_p->clear_ctrl_stack = as_screen_clear_ctrl_stack;
    screen_p->get_ctrl_counts = as_screen_get_ctrl_counts;
    screen_p->penevt_hdlr = as_screen_penevt_hdlr;
    screen_p->keyevt_hdlr = as_screen_keyevt_hdlr;
    screen_p->set_bg_color = as_screen_set_bg_color;
    screen_p->set_bg_image = as_screen_set_bg_image;
    screen_p->clear = as_screen_clear;
    screen_p->bg_color = AS_COLOR_WHITE;
    screen_p->goback = as_screen_goback;
    as_reset_layer_clip(0);
#if defined(AS_RUN_ON_SKY)
    as_reset_clip();
#endif
    as_disable_flush();

    switch(screen_type)
    {
#ifdef AS_TEST_SCREEN_ENABLE

        case AS_SCREEN_TEST:
            as_test_screen_init(screen_p);
            break;
#endif

        case AS_SCREEN_LOADING:
            as_loading_screen_init(screen_p);
            break;

        case AS_SCREEN_OPTION:
            as_option_screen_init(screen_p);
            break;

        case AS_SCREEN_POPUP:
            as_popup_screen_init(screen_p);
            break;

        case AS_SCREEN_CONFIRM:
            as_confirm_screen_init(screen_p);
            break;

        case AS_SCREEN_WAITING:
            as_waiting_screen_init(screen_p);
            break;

        case AS_SCREEN_NUMBER:
            as_number_screen_init(screen_p);
            break;

        case AS_SCREEN_DATETIME:
            as_datetime_screen_init(screen_p);
            break;

        case AS_SCREEN_CUSTOM:
            as_custom_screen_init(screen_p);
            break;

        case AS_SCREEN_FTDATA:
            as_ftdata_screen_init(screen_p);
            break;

        case AS_SCREEN_FTTYPE:
            as_fttype_screen_init(screen_p);
            break;

        case AS_SCREEN_FTDETAIL:
            as_ftdetail_screen_init(screen_p);
            break;

        case AS_SCREEN_FTSTAT:
            as_ftstat_screen_init(screen_p);
            break;

        case AS_SCREEN_FTSTAT_SUB:
            as_ftstatsub_screen_init(screen_p);
            break;

        case AS_SCREEN_FTSETTING:
            as_ft_setting_screen_init(screen_p);
            break;

        case AS_SCREEN_FTABOUT:
            as_ft_about_screen_init(screen_p);
            break;

        case AS_SCREEN_FTABOUT_SUB:
            as_ft_aboutsub_screen_init(screen_p);
            break;

        default:
            break;
    }

    if(!screen_p->is_small_screen)
    {
        screen_p->clear();
    }

    as_enable_flush();
#if defined(AS_RUN_ON_SKY)
    as_reset_clip();
#endif
    return AS_OK;
}

as_ret as_screen_deinit(as_screen* screen_p)
{
    as_ret ret = AS_OK;

    if(!screen_p)
    {
        ret = AS_INVALID_PARAM;
        return ret;
    }

    switch(screen_p->screen_type)
    {
#ifdef AS_TEST_SCREEN_ENABLE

        case AS_SCREEN_TEST:
            as_test_screen_deinit(screen_p);
            break;
#endif

        case AS_SCREEN_LOADING:
            as_loading_screen_deinit(screen_p);
            break;

        case AS_SCREEN_OPTION:
            as_option_screen_deinit(screen_p);
            break;

        case AS_SCREEN_POPUP:
            as_popup_screen_deinit(screen_p);
            break;

        case AS_SCREEN_CONFIRM:
            as_confirm_screen_deinit(screen_p);
            break;

        case AS_SCREEN_WAITING:
            as_waiting_screen_deinit(screen_p);
            break;

        case AS_SCREEN_NUMBER:
            as_number_screen_deinit(screen_p);
            break;

        case AS_SCREEN_DATETIME:
            as_datetime_screen_deinit(screen_p);
            break;

        case AS_SCREEN_CUSTOM:
            as_custom_screen_deinit(screen_p);
            break;

        case AS_SCREEN_FTDATA:
            as_ftdata_screen_deinit(screen_p);
            break;

        case AS_SCREEN_FTTYPE:
            as_fttype_screen_deinit(screen_p);
            break;

        case AS_SCREEN_FTDETAIL:
            as_ftdetail_screen_deinit(screen_p);
            break;

        case AS_SCREEN_FTSTAT:
            as_ftstat_screen_deinit(screen_p);
            break;

        case AS_SCREEN_FTSTAT_SUB:
            as_ftstatsub_screen_deinit(screen_p);
            break;

        case AS_SCREEN_FTSETTING:
            as_ft_setting_screen_deinit(screen_p);
            break;

        case AS_SCREEN_FTABOUT:
            as_ft_about_screen_deinit(screen_p);
            break;

        case AS_SCREEN_FTABOUT_SUB:
            as_ft_aboutsub_screen_deinit(screen_p);
            break;

        default:
            break;
    }

    //free the controls list
    screen_p->clear_ctrl_stack(screen_p);
    return ret;
}

